package org.happy.tester.catcher.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import org.happy.tester.catcher.service.MockService;
import org.happy.tester.catcher.util.JenkinsUtil;
import org.happy.tester.catcher.util.LocalCacheUtil;
import org.happy.tester.common.http.req.MockResultRequest;
import org.happy.tester.common.model.MockResultDO;
import org.happy.tester.common.model.ResultDO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

import static org.happy.tester.common.constant.CommonConstant.POINTCUT_JOINER;

/**
 * @Classname MockServiceImpl
 * @Description TODO
 * @Date 2020/4/11 2:29 下午
 * @Created by jc.bai
 */
@Service
public class MockServiceImpl implements MockService {

    @Resource
    private JenkinsUtil jenkinsUtil;

    @Override
    public boolean needMock(String pointcut) {
        List<String> needMockPointcuts = LocalCacheUtil.POINTCUTS_CACHE.get(LocalCacheUtil.NEED_MOCK);
        return Optional.ofNullable(needMockPointcuts).orElse(new ArrayList<>()).contains(pointcut);
    }

    @Override
    public Object getMockResult(String pointcut) {
        String result = LocalCacheUtil.RESULT_AFTER_MOCK_CACHE.get(pointcut);
        Object resultObj = JSONObject.parseObject(result, Object.class);
        return resultObj;
    }

    @Override
    public void fixMockResult(List<MockResultRequest> mockResultRequestList) {
        //清空 mock cache
        LocalCacheUtil.POINTCUTS_CACHE.put(LocalCacheUtil.NEED_MOCK, new ArrayList<>());
        mockResultRequestList.stream().forEach(mockResultRequest -> {
            List<MockResultDO> mockResultDOList = mockResultRequest.getMockResultDOList();
            mockResultDOList.stream().forEach(mockResultDO -> {
                String paramTypes = null;
                if (mockResultDO.getPointcutDO().getParamsTypeArray() != null) {
                    paramTypes = Arrays.toString(mockResultDO.getPointcutDO().getParamsTypeArray());
                    paramTypes = paramTypes.substring(1, paramTypes.length() - 1);
                }
                String pointcut = POINTCUT_JOINER.join(mockResultRequest.getAppIp(),
                        mockResultDO.getPointcutDO().getClassName(),
                        mockResultDO.getPointcutDO().getMethodName(),
                        paramTypes,
                        mockResultRequest.getClientIp());
                //打 mock 标
                LocalCacheUtil.POINTCUTS_CACHE.get(LocalCacheUtil.NEED_MOCK).add(pointcut);
                //修改 mockResult
                doFix(pointcut, mockResultDO.getResultDO());
                List<String> needCollect = LocalCacheUtil.POINTCUTS_CACHE.get(LocalCacheUtil.NEED_COLLECT);
                ListIterator<String> listIterator = needCollect.listIterator();
                while (listIterator.hasNext()) {
                    String exitPointcut = listIterator.next();
                    if (exitPointcut.equals(pointcut)) {
                        listIterator.remove();
                    }
                }
                /*try {
                    jenkinsUtil.deployAgentLoader(mockResultRequest.convertToPointcutRequest());
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }*/
            });
        });
    }

    private void doFix(String pointcut, ResultDO resultDO) {
        String realResult = LocalCacheUtil.RESULT_COLLECTED_CACHE.get(pointcut);
        JSONObject realResultJson = JSONObject.parseObject(realResult);
        JSONObject resultJson = JSONObject.parseObject(resultDO.getResult());
        List<String> toDelKeys = resultJson.getObject("del", List.class);
        if (toDelKeys != null && toDelKeys.size() > 0) {
            for (String key : toDelKeys) {
                //通过 path 删除 json 中的元素
                JSONPath.remove(realResultJson, key);
            }
        }
        Map<String, Object> toSetResult = resultJson.getObject("set", Map.class);
        if (toSetResult != null) {
            for (Map.Entry<String, Object> resultMap : toSetResult.entrySet()) {
                //如果 path 存在就update，不存在就 add
                JSONPath.set(realResultJson, resultMap.getKey(), resultMap.getValue());
            }
        }
        LocalCacheUtil.RESULT_AFTER_MOCK_CACHE.put(pointcut, realResultJson.toJSONString());
    }
}
